/**
 * @file empfaenger.c
 * Betriebssysteme - Beispiel 3
 *
 * @author Christian Lachner <ic11b010@technikum-wien.at>
 * @author Max Paflik <ic11b006@technikum-wien.at>
 * @date 2012/06/03
 *
 * @version $Revision: 7 $
 *
 * URL: $HeadURL$
 *
 * Last Modified: $Author: Chris $
 */

#include "myrxtx.h"

int main(int argc, char * argv[]) {
	int bufsize;
	int semid_r = -1;
	int semid_w = -1;
	int shmid = -1;
	int * shmptr = NULL;
	int i = 0;
	int j = 0;
#if DEBUG > 0
	unsigned int bytecount = 0;
#endif

	if((bufsize = handle_params(argc, argv)) != MYRXTX_ERROR) {
		/* init/grab write-semaphore and fetch it's id */
		if((semid_w = init_sem(SEMKEY_W, bufsize)) == MYRXTX_ERROR) {
			cleanup(&semid_r, &semid_w, &shmid, shmptr);
			return EXIT_FAILURE;
		}

		/* init/grab read-semaphore and fetch it's id */
		if((semid_r = init_sem(SEMKEY_R, 0)) == MYRXTX_ERROR) {
			cleanup(&semid_r, &semid_w, &shmid, shmptr);
			return EXIT_FAILURE;
		}

		/* init/grab SHM and fetch it's id */
		if((shmid = init_shm(SHMKEY, bufsize)) == MYRXTX_ERROR) {
			cleanup(&semid_r, &semid_w, &shmid, shmptr);
			return EXIT_FAILURE;
		}

		/* attach SHM segment */
		if((shmptr = shmat(shmid, NULL, 0)) == (void *) -1) {
			print_error_eno(errno);
			cleanup(&semid_r, &semid_w, &shmid, shmptr);
			return EXIT_FAILURE;
		}
		
#if DEBUG > 0
		fprintf(stderr, "DEBUG: RX = r\n");
#endif

		do {
			/* wait for the semaphore */
			while(P(semid_r) == -1) {
				if(errno != EINTR) {
					print_error_msg("Error while waiting for the reading semaphore!");
					cleanup(&semid_r, &semid_w, &shmid, shmptr);
					return EXIT_FAILURE;
				}
#if DEBUG > 0
				else {
					fprintf(stderr, "w\nDEBUG: %s: Process interruped! waiting...\n", thisfname);
				}
#endif
			}

			j = shmptr[i];

			/* signals to the semaphore */
			if(V(semid_w) == -1) {
				print_error_msg("Error while sending signals to writing semaphore!");
				cleanup(&semid_r, &semid_w, &shmid, shmptr);
				return EXIT_FAILURE;
			}

			if(j != EOF) {
				if(fputc(j, stdout) < 0) {
					print_error_msg("Error while writing characters to stdout!");
					cleanup(&semid_r, &semid_w, &shmid, shmptr);
					return EXIT_FAILURE;
				}
			}

			i++;

#if DEBUG > 0
			bytecount++;
			if(bytecount % DEBUG_BC_DIVISOR == 0) {
				fprintf(stderr, "r");
				fflush(stderr);
				bytecount = 0;
			}
#endif

			if(i >= bufsize) {
				i = 0;
			}
		} while(j != EOF);

#if DEBUG > 0
		fprintf(stderr, "!\n");
#endif

		/* flush stdout to make sure everything got written */
		if(fflush(stdout) != 0) {
			print_error_eno(errno);
		}
#if DEBUG > 0
		else {
			fprintf(stderr, "DEBUG: %s: Flush of stdout successful.\n", thisfname);
		}
#endif

		cleanup(&semid_r, &semid_w, &shmid, shmptr);
	} else {
		print_usage();
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}
